package com.atlyc.common.config;

import com.wyebus.boss.common.exception.RRException;
import com.wyebus.boss.common.utils.StringTool;

import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import java.lang.reflect.Constructor;
import java.math.BigDecimal;
import java.util.List;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class ValidatorUtils {

    private static final String CHINESE_CARD_ID = "(^\\d{14}([0-9]|x|X){1}$)|(^\\d{17}([0-9]|x|X){1}$)";

    private static Validator validator;

    static {
        validator = Validation.buildDefaultValidatorFactory().getValidator();
    }

    /**
     * 校验hibernate-validator对象
     *
     * 参考文档：http://docs.jboss.org/hibernate/validator/5.4/reference/en-US/html_single/
     * 
     * @param object        待校验对象
     * @param groups        待校验的组
     * @throws RRException  校验不通过，则报RRException异常
     */
    public static void validateEntity(Object object, Class<?>... groups) throws RRException {
        Set<ConstraintViolation<Object>> constraintViolations = validator.validate(object, groups);
        if (!constraintViolations.isEmpty()) {
            ConstraintViolation<Object> constraint = (ConstraintViolation<Object>) constraintViolations.iterator()
                    .next();
            throw new RRException(constraint.getMessage());
        }
    }

    /**
     * 检查参数是否为空
     * 
     * @param obj
     * @param message
     * @throws FieldException
     */
    public static void checkEmpty(Object obj, String message) throws FieldException {
        if (obj == null) {
            throw new FieldException(message);
        }
    }

    /**
     * 检查字符类型参数是否为空
     * 
     * @param id
     * @param message
     * @throws FieldException
     */
    public static void checkEmpty(String id, String message) throws FieldException {
        if (StringTool.isTrimEmpty(id)) {
            throw new FieldException(message);
        }
    }

    /**
     * 检查字符类型参数是否为空
     * 
     * @param value
     * @param name
     * @return
     * @throws FieldException
     */
    public static String checkString(String value, String name) throws FieldException {
        if (StringTool.isEmpty(value)) {
            throw new FieldException(name + "不能为空");
        }
        return value.trim();
    }

    public static void checkLong(Long val, String name) throws FieldException {
        if (val == null || val.longValue() <= 0) {
            throw new FieldException(name + "不能为空");
        }
    }

    /**
     * 检查非负整数
     * 
     * @param obj
     * @param fieldName
     * @throws FieldException
     */
    public static void checkNotNegativeLong(Long obj, String fieldName) throws FieldException {
        checkEmpty(obj, fieldName + "不能为空");
        if (obj < 0) {
            throw new FieldException(fieldName + "不能小于0");
        }
    }

    /**
     * 检查列表是否为空
     * 
     * @param list
     * @param name
     * @throws FieldException
     */
    @SuppressWarnings("rawtypes")
    public static void checkList(List list, String name) throws FieldException {
        checkEmpty(list, "列表不能为空");
        if (list.isEmpty()) {
            throw new FieldException(name + "不能为空");
        }
    }

    /**
     * 检查整数类型参数是否为空及格式是否正确，并进行格式转换
     * 
     * @param value
     * @param name
     * @return
     * @throws FieldException
     */
    public static Integer checkInteger(String value, String name) throws FieldException {
        if (StringTool.isEmpty(value)) {
            throw new FieldException(name + "不能为空");
        }

        try {
            return new Integer(value);
        } catch (Exception e) {
            throw new FieldException(name + "格式不正确");
        }
    }

    /**
     * 检查金钱或浮点类型数值是否为空及格式是正确，并进行格式转换
     * 
     * @param value
     * @param name
     * @return
     * @throws FieldException
     */
    public static BigDecimal checkBigDecimal(String value, String name) throws FieldException {
        if (StringTool.isEmpty(value)) {
            throw new FieldException(name + "不能为空");
        }

        try {
            return new BigDecimal(value);
        } catch (Exception e) {
            throw new FieldException(name + "格式不正确");
        }
    }

    /**
     * @category 字符串转换成数字类型
     * @param value
     *            数字字符串
     * @param numberClass
     *            数字类型Class
     */
    @SuppressWarnings("unchecked")
    public static <T> T parseNumber(String value, String name, Class<? extends Number> numberClass)
            throws FieldException {
        if (StringTool.isTrimEmpty(value)) {
            return null;
        }
        try {
            Constructor<T> constructor = (Constructor<T>) numberClass.getConstructor(String.class);
            T number = constructor.newInstance(value);
            return number;
        } catch (Exception e) {
            throw new FieldException(name + "格式不正确");
        }
    }

    /**
     * 检查正整数
     * 
     * @param obj
     * @param fieldName
     * @throws FieldException
     */
    public static void checkNotNegativeInteger(Integer obj, String fieldName) throws FieldException {
        checkEmpty(obj, fieldName + "不能为空");
        if (obj < 0) {
            throw new FieldException(fieldName + "不能小于0");
        }
    }

    /**
     * 检查正整数
     * 
     * @param obj
     * @param fieldName
     * @throws FieldException
     */
    public static void checkPositiveInteger(String obj, String fieldName) throws FieldException {
        checkEmpty(obj, fieldName + "不能为空");
        int intValue;
        try {
            intValue = Integer.parseInt(obj);
        } catch (Exception e) {
            throw new FieldException(fieldName + "格式不正确");
        }
        if (intValue < 0) {
            throw new FieldException(fieldName + "不能小于0");
        }
    }

    /**
     * 检查金额
     * 
     * @param obj
     * @param fieldName
     * @throws FieldException
     */
    public static void checkBigDecimal(BigDecimal obj, String fieldName) throws FieldException {
        checkEmpty(obj, fieldName + "不能为空");
        if (obj.doubleValue() < 0) {
            throw new FieldException(fieldName + "不能小于0");
        }
    }

    /**
     * 检查身份证号
     * 
     * @param obj
     * @throws FieldException
     */
    public static void checkIdentityCard(String obj) throws FieldException {
        checkString(obj, "身份证号");
        Pattern pattern = Pattern.compile(CHINESE_CARD_ID);
        Matcher matcher = pattern.matcher(obj);
        if (!matcher.find()) {
            throw new FieldException("身份证号格式不正确");
        }
    }

    /**
     * 检查金额
     * 
     * @param obj
     * @param fieldName
     * @throws FieldException
     */
    public static void checkPositiveBigDecimal(String obj, String fieldName) throws FieldException {
        checkEmpty(obj, fieldName + "不能为空");
        BigDecimal bigDecimal;
        try {
            bigDecimal = new BigDecimal(obj);
        } catch (Exception e) {
            throw new FieldException(fieldName + "格式不正确");
        }

        if (bigDecimal.doubleValue() < 0) {
            throw new FieldException(fieldName + "不能小于0");
        }
    }

}
